home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / utils / nroff~06.zoo / escape.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-16  |  22.1 KB  |  1,227 lines

  1. static char *rcsid_escape_c="$Id: escape.c,v 1.2 1992/07/16 10:38:32 rosenkra Exp $";
  2.  
  3. /*
  4.  * $Log: escape.c,v $
  5.  * Revision 1.2  1992/07/16  10:38:32  rosenkra
  6.  * port to gcc, add tm,ie,el
  7.  *
  8.  */
  9.  
  10. /*
  11.  *    escape.c - Escape and special character input processing portion of
  12.  *               nroff word processor
  13.  *
  14.  *    adapted for atariST/TOS by Bill Rosenkranz 11/89
  15.  *    net:    rosenkra@convex.com
  16.  *    CIS:    71460,17
  17.  *    GENIE:    W.ROSENKRANZ
  18.  *
  19.  *    original author:
  20.  *
  21.  *    Stephen L. Browning
  22.  *    5723 North Parker Avenue
  23.  *    Indianapolis, Indiana 46220
  24.  *
  25.  *    history:
  26.  *
  27.  *    - Originally written in BDS C;
  28.  *    - Adapted for standard C by W. N. Paul
  29.  *    - Heavily hacked up to conform to "real" nroff by Bill Rosenkranz
  30.  */
  31.  
  32. #undef NRO_MAIN                    /* extern globals */
  33.  
  34. #include <stdio.h>
  35. #include "nroff.h"
  36.  
  37.  
  38. /*------------------------------*/
  39. /*    expesc            */
  40. /*------------------------------*/
  41. void expesc (p, q)
  42. char   *p;
  43. char   *q;
  44. {
  45.  
  46. /*
  47.  *    Expand escape sequences
  48.  */
  49.  
  50.     REGISTER char  *s;
  51.     REGISTER char  *t;
  52.     REGISTER char  *pstr;
  53.     REGISTER int    i;
  54.     REGISTER int    val;
  55.     REGISTER int    autoinc;
  56.     char        c;
  57.     char        fs[20];                /* for font change */
  58.     char        nrstr[20];
  59.     char        fmt[20];
  60.     char        name[10];
  61.     int        nreg;
  62.     char           *pfs;
  63.     int        inc;
  64.     int        tmp;
  65.     char        delim;
  66.  
  67.  
  68.     s = p;
  69.     t = q;
  70.  
  71.  
  72.     /*
  73.      *   if escape parsing is not on, just copy string
  74.      */
  75.     if (dc.escon == NO)
  76.     {
  77.         while (*s != EOS)
  78.         {
  79.             *t++ = *s++;
  80.         }
  81.         *t = EOS;
  82.         strcpy (p, q);
  83.  
  84.         return;
  85.     }
  86.  
  87.  
  88.     /*
  89.      *   do it...
  90.      */
  91.     while (*s != EOS)
  92.     {
  93.         if (*s != dc.escchr)
  94.         {
  95.             /*
  96.              *   not esc, continue...
  97.              */
  98.             *t++ = *s++;
  99.         }
  100.  
  101.  
  102.         else if (*(s + 1) == dc.escchr)
  103.         {
  104.             /*
  105.              *   \\            escape escape
  106.              */
  107.             *t++ = *s++;
  108.             ++s;
  109.         }
  110.  
  111.  
  112.         else if (*(s + 1) == 'n')
  113.         {
  114.             /*
  115.              *   \nx, \n(xx        register
  116.              *
  117.              *   first check for \n+... or \n-... (either form)
  118.              */
  119.             s += 2;
  120.             autoinc = 0;
  121.             if (*s == '+')
  122.             {
  123.                 autoinc = 1;
  124.                 s += 1;
  125.             }
  126.             if (*s == '-')
  127.             {
  128.                 autoinc = -1;
  129.                 s += 1;
  130.             }
  131.  
  132.  
  133.  
  134.             /*
  135.              *   was this \nx or \n(xx form?
  136.              */
  137.             if (isalpha (*s))
  138.             {
  139.                 /*
  140.                  *   \nx form. find reg (a-z)
  141.                  */
  142.                 nreg = tolower (*s) - 'a';
  143.  
  144.  
  145.                 /*
  146.                  *   was this \n+x or \n-x? if so, do the
  147.                  *   auto incr
  148.                  */
  149.                 if (autoinc > 0)
  150.                     dc.nr[nreg] += dc.nrauto[nreg];
  151.                 else if (autoinc < 0)
  152.                     dc.nr[nreg] -= dc.nrauto[nreg];
  153.  
  154.                 /*
  155.                  *   display format
  156.                  */
  157.                 if (dc.nrfmt[nreg] == '1')
  158.                 {
  159.                     /*
  160.                      *   normal decimal digits
  161.                      */
  162.                     t += itoda (dc.nr[nreg], t, 6) - 1;
  163.                 }
  164.                 else if (dc.nrfmt[nreg] == 'i')
  165.                 {
  166.                     /*
  167.                      *   lower roman
  168.                      */
  169.                     t += itoroman (dc.nr[nreg], t, 24) - 1;
  170.                 }
  171.                 else if (dc.nrfmt[nreg] == 'I')
  172.                 {
  173.                     /*
  174.                      *   upper roman
  175.                      */
  176.                     t += itoROMAN (dc.nr[nreg], t, 24) - 1;
  177.                 }
  178.                 else if (dc.nrfmt[nreg] == 'a')
  179.                 {
  180.                     /*
  181.                      *   lower letters
  182.                      */
  183.                     t += itoletter (dc.nr[nreg], t, 12) - 1;
  184.                 }
  185.                 else if (dc.nrfmt[nreg] == 'A')
  186.                 {
  187.                     /*
  188.                      *   upper letters
  189.                      */
  190.                     t += itoLETTER (dc.nr[nreg], t, 12) - 1;
  191.                 }
  192.                 else if (dc.nrfmt[nreg] & 0x80)
  193.                 {
  194.                     /*
  195.                      *   zero-filled decimal
  196.                      */
  197.                     sprintf (fmt, "%%0%dld",
  198.                         (int)(dc.nrfmt[nreg] & 0x7F));
  199.                     fmt[5] = '\0';
  200.                     sprintf (nrstr, fmt, (long) dc.nr[nreg]);
  201.                     tmp = dc.nrfmt[nreg] & 0x7F;
  202.                     nrstr[tmp] = '\0';
  203.  
  204.                     strcpy (t, nrstr);
  205.                     t += strlen (nrstr);
  206.                 }
  207.                 else
  208.                 {
  209.                     /*
  210.                      *   normal (default)
  211.                      */
  212.                     t += itoda (dc.nr[nreg], t, 6) - 1;
  213.                 }
  214.                 ++s;
  215.             }
  216.             else if (*s == '%')
  217.             {
  218.                 /*
  219.                  *   \n% form. find index into reg struct
  220.                  */
  221.                 nreg = findreg ("%");
  222.                 if (nreg < 0)
  223.                 {
  224.                     fprintf (err_stream,
  225.                         "***%s: no register match (%%)\n",
  226.                         myname);
  227.                     err_exit (-1);
  228.                 }
  229.  
  230.  
  231.                 /*
  232.                  *   was this \n+% or \n-%? if so, do the
  233.                  *   auto incr
  234.                  */
  235.                 if (autoinc > 0)
  236.                     rg[nreg].rval += rg[nreg].rauto;
  237.                 else if (autoinc < 0)
  238.                     rg[nreg].rval -= rg[nreg].rauto;
  239.  
  240.  
  241.                 /*
  242.                  *   display format
  243.                  */
  244.                 if (rg[nreg].rfmt == '1')
  245.                 {
  246.                     /*
  247.                      *   normal decimal digits
  248.                      */
  249.                     t += itoda (rg[nreg].rval, t, 6) - 1;
  250.                 }
  251.                 else if (rg[nreg].rfmt == 'i')
  252.                 {
  253.                     /*
  254.                      *   lower roman
  255.                      */
  256.                     t += itoroman (rg[nreg].rval, t, 24) - 1;
  257.                 }
  258.                 else if (rg[nreg].rfmt == 'I')
  259.                 {
  260.                     /*
  261.                      *   upper roman
  262.                      */
  263.                     t += itoROMAN (rg[nreg].rval, t, 24) - 1;
  264.                 }
  265.                 else if (rg[nreg].rfmt == 'a')
  266.                 {
  267.                     /*
  268.                      *   lower letters
  269.                      */
  270.                     t += itoletter (rg[nreg].rval, t, 12) - 1;
  271.                 }
  272.                 else if (rg[nreg].rfmt == 'A')
  273.                 {
  274.                     /*
  275.                      *   upper letters
  276.                      */
  277.                     t += itoLETTER (rg[nreg].rval, t, 12) - 1;
  278.                 }
  279.                 else if (rg[nreg].rfmt & 0x80)
  280.                 {
  281.                     /*
  282.                      *   zero-filled decimal
  283.                      */
  284.                     sprintf (fmt, "%%0%dld",
  285.                         (int)(rg[nreg].rfmt & 0x7F));
  286.                     fmt[5] = '\0';
  287.                     sprintf (nrstr, fmt, (long) rg[nreg].rval);
  288.                     tmp = rg[nreg].rfmt & 0x7F;
  289.                     nrstr[tmp] = '\0';
  290.  
  291.                     strcpy (t, nrstr);
  292.                     t += strlen (nrstr);
  293.                 }
  294.                 else
  295.                 {
  296.                     /*
  297.                      *   normal (default)
  298.                      */
  299.                     t += itoda (rg[nreg].rval, t, 6) - 1;
  300.                 }
  301.                 s += 1;
  302.             }
  303.             else if (*s == '(')
  304.             {
  305.                 /*
  306.                  *   \n(xx form. find index into reg struct
  307.                  */
  308.                 s += 1;
  309.                 name[0] = *s;
  310.                 name[1] = *(s + 1);
  311.                 if (name[1] == ' '  || name[1] == '\t'
  312.                 ||  name[1] == '\n' || name[1] == '\r')
  313.                     name[1] = '\0';
  314.                 name[2] = '\0';
  315.                 nreg = findreg (name);
  316.                 if (nreg < 0)
  317.                 {
  318.                     fprintf (err_stream,
  319.                         "***%s: no register match (%s)\n",
  320.                         myname, name);
  321.                     err_exit (-1);
  322.                 }
  323.                 
  324.  
  325.                 /*
  326.                  *   was this \n+(xx or \n-(xx? if so, do the
  327.                  *   auto incr
  328.                  */
  329.                 if (rg[nreg].rflag & RF_WRITE)
  330.                 {
  331.                     if (autoinc > 0)
  332.                         rg[nreg].rval += rg[nreg].rauto;
  333.                     else if (autoinc < 0)
  334.                         rg[nreg].rval -= rg[nreg].rauto;
  335.                 }
  336.  
  337.  
  338.                 /*
  339.                  *   display format
  340.                  */
  341.                 if (rg[nreg].rfmt == '1')
  342.                 {
  343.                     /*
  344.                      *   normal decimal digits
  345.                      */
  346.                     t += itoda (rg[nreg].rval, t, 6) - 1;
  347.                 }
  348.                 else if (rg[nreg].rfmt == 'i')
  349.                 {
  350.                     /*
  351.                      *   lower roman
  352.                      */
  353.                     t += itoroman (rg[nreg].rval, t, 24) - 1;
  354.                 }
  355.                 else if (rg[nreg].rfmt == 'I')
  356.                 {
  357.                     /*
  358.                      *   upper roman
  359.                      */
  360.                     t += itoROMAN (rg[nreg].rval, t, 24) - 1;
  361.                 }
  362.                 else if (rg[nreg].rfmt == 'a')
  363.                 {
  364.                     /*
  365.                      *   lower letters
  366.                      */
  367.                     t += itoletter (rg[nreg].rval, t, 12) - 1;
  368.                 }
  369.                 else if (rg[nreg].rfmt == 'A')
  370.                 {
  371.                     /*
  372.                      *   upper letters
  373.                      */
  374.                     t += itoLETTER (rg[nreg].rval, t, 12) - 1;
  375.                 }
  376.                 else if (rg[nreg].rfmt & 0x80)
  377.                 {
  378.                     /*
  379.                      *   zero-filled decimal
  380.                      */
  381.                     sprintf (fmt, "%%0%dld",
  382.                         (int)(rg[nreg].rfmt & 0x7F));
  383.                     fmt[5] = '\0';
  384.                     sprintf (nrstr, fmt, (long) rg[nreg].rval);
  385.                     tmp = rg[nreg].rfmt & 0x7F;
  386.                     nrstr[tmp] = '\0';
  387.  
  388.                     strcpy (t, nrstr);
  389.                     t += strlen (nrstr);
  390.                 }
  391.                 else
  392.                 {
  393.                     /*
  394.                      *   normal (default)
  395.                      */
  396.                     t += itoda (rg[nreg].rval, t, 6) - 1;
  397.                 }
  398.                 s += 2;
  399.             }
  400.         }
  401.  
  402.  
  403.         else if (*(s + 1) == '\"')
  404.         {
  405.             /*
  406.              *   \"            comment
  407.              */
  408.             *s = EOS;
  409.             *t = *s;
  410.  
  411.             return;
  412.         }
  413.  
  414.  
  415.         else if (*(s + 1) == '*')
  416.         {
  417.             /*
  418.              *   \*x, \*(xx        string
  419.              */
  420.             s += 2;
  421.             if (*s == '(')
  422.             {
  423.                 /*
  424.                  *   \*(xx form
  425.                  */
  426.                 s += 1;
  427.                 name[0] = *s;
  428.                 name[1] = *(s + 1);
  429.                 name[2] = '\0';
  430.                 pstr = getstr (name);
  431.                 if (!pstr)
  432.                 {
  433.                     fprintf (err_stream,
  434.                         "***%s: string not found (\\*(%s)\n",
  435.                         myname, name);
  436.                     err_exit (-1);
  437.                 }
  438.                 while (*pstr)
  439.                     *t++ = *pstr++;
  440.                 s += 2;
  441.             }
  442.             else
  443.             {
  444.                 /*
  445.                  *   \*x form
  446.                  */
  447.                 name[0] = *s;
  448.                 name[1] = '\0';
  449.                 pstr = getstr (name);
  450.                 if (!pstr)
  451.                 {
  452.                     fprintf (err_stream,
  453.                         "***%s: string not found (\\*%s)\n",
  454.                         myname, name);
  455.                     err_exit (-1);
  456.                 }
  457.                 while (*pstr)
  458.                     *t++ = *pstr++;
  459.                 s += 1;
  460.             }
  461.         }
  462.  
  463.  
  464.         else if (*(s + 1) == 'f')
  465.         {
  466.             /*
  467.              *   \fx        font
  468.              */
  469.             s += 2;
  470.             pfs = fs;        /* set up ret string */
  471.             fs[0] = '\0';
  472.  
  473.             /*
  474.              *  it parses 1 char of s and returns esc seq for
  475.              *  \fB, \fS, \fI, and \fR
  476.              */
  477.             fontchange (*s, pfs);
  478.  
  479.             /*
  480.              *   imbed the atari vt52 or ANSI escape seq
  481.              */
  482.             while (*pfs)
  483.                 *t++ = *pfs++;
  484.             ++s;            /* skip B,I,R,S,P */
  485.         }
  486.  
  487.  
  488.         else if (*(s + 1) == '(')
  489.         {
  490.             /*
  491.              *   \(xx        special char
  492.              */
  493.             s  += 2;        /* s points to xx */
  494.  
  495.             if (ansi_escapes)
  496.             {
  497.                 /*
  498.                  *   it returns num char to skip and sets c to
  499.                  *   the ascii value of the char
  500.                  */
  501.                 inc = specialchar (s, &c);
  502.  
  503.                 /*
  504.                  *   skip proper num char in s and add c to
  505.                  *   target
  506.                  */
  507.                 if (inc)
  508.                 {
  509.                     /*
  510.                      *   skip past the xx
  511.                      */
  512.                     s   += inc;
  513.  
  514.                     /*
  515.                      *   imbed special char escape seq.
  516.                      *   we should put out something like:
  517.                      *
  518.                      *    ESC [ 9 m c ESC [ m
  519.                      *
  520.                      *   "c" is the ascii char in the
  521.                      *   alt char set. we return to normal
  522.                      *   mode (font) immediately so if u
  523.                      *   want to continue bold, you will
  524.                      *   have to do another \fB. alt char
  525.                      *   set is mutually exclusive.
  526.                      */
  527.                     strcpy (t, s_special);    /* start...*/
  528.                     t   += strlen (s_special);
  529.  
  530.                     *t++ = c;        /* the char */
  531.  
  532.                     strcpy (t, e_special);    /* ...end */
  533.                     t   += strlen (e_special);
  534.                 }
  535.             }
  536.             else
  537.             {
  538.                 /*
  539.                  *   it returns num char to skip and sets c to
  540.                  *   the ascii value of the char
  541.                  */
  542.                 inc = specialchar (s, &c);
  543.  
  544.                 /*
  545.                  *   skip proper num char in s and add c to
  546.                  *   target
  547.                  */
  548.                 if (inc)
  549.                 {
  550.                     s   += inc;
  551.                     *t++ = c;
  552.                 }
  553.             }
  554.         }
  555.  
  556.  
  557.         else if (*(s + 1) == 'e')
  558.         {
  559.             /*
  560.              *   \e        printable version of escape
  561.              */
  562.             *t++ = dc.escchr;
  563.             s   += 2;
  564.         }
  565.  
  566.  
  567.         else if (*(s + 1) == '`')
  568.         {
  569.             /*
  570.              *   \`        grave, like \(ga
  571.              */
  572.             *t++ = 0x60;
  573.             s  += 2;
  574.         }
  575.  
  576.  
  577.         else if (*(s + 1) == '\'')
  578.         {
  579.             /*
  580.              *   \'        accute, like \(aa
  581.              */
  582.             s  += 2;
  583.             *t++ = 0xBA;
  584.         }
  585.  
  586.  
  587.         else if (*(s + 1) == '-')
  588.         {
  589.             /*
  590.              *   \-        minus
  591.              */
  592.             s  += 2;
  593.             *t++ = 0x2D;
  594.         }
  595.  
  596.  
  597.         else if (*(s + 1) == '.')
  598.         {
  599.             /*
  600.              *   \.        period
  601.              */
  602.             s  += 2;
  603.             *t++ = 0x2E;
  604.         }
  605.  
  606.  
  607.         else if (*(s + 1) == ' ')
  608.         {
  609.             /*
  610.              *   \(space)    space
  611.              */
  612.             s  += 2;
  613.             *t++ = 0x20;
  614.         }
  615.  
  616.  
  617.         else if (*(s + 1) == '0')
  618.         {
  619.             /*
  620.              *   \0        digital width space
  621.              */
  622.             s  += 2;
  623.             *t++ = 0x20;
  624.         }
  625.  
  626.  
  627.         else if (*(s + 1) == '|')
  628.         {
  629.             /*
  630.              *   \|        narrow width char (0 in nroff)
  631.              */
  632.             s  += 2;
  633.         }
  634.  
  635.  
  636.         else if (*(s + 1) == '^')
  637.         {
  638.             /*
  639.              *   \^        narrow width char (0 in nroff)
  640.              */
  641.             s  += 2;
  642.         }
  643.  
  644.  
  645.         else if (*(s + 1) == '&')
  646.         {
  647.             /*
  648.              *   \&        non-printing zero width
  649.              */
  650.             s  += 2;
  651.         }
  652.  
  653.  
  654.         else if (*(s + 1) == '!')
  655.         {
  656.             /*
  657.              *   \!        transparent copy line
  658.              */
  659.             s  += 2;
  660.         }
  661.  
  662.  
  663.         else if (*(s + 1) == '$')
  664.         {
  665.             /*
  666.              *   \$N    interpolate arg 1<=N<=9
  667.              */
  668.             s  += 2;
  669.         }
  670.  
  671.  
  672.         else if (*(s + 1) == '%')
  673.         {
  674.             /*
  675.              *   \%        hyphen
  676.              */
  677.             s  += 2;
  678.             *t++ = 0x2D;
  679.             *t++ = 0x2D;
  680.         }
  681.  
  682.  
  683.         else if (*(s + 1) == 'a')
  684.         {
  685.             /*
  686.              *   \a        leader char
  687.              */
  688.             s  += 2;
  689.         }
  690.  
  691.  
  692.         else if (*(s + 1) == 'b')
  693.         {
  694.             /*
  695.              *   \b'abc...'    bracket building function
  696.              */
  697.             s  += 2;
  698.         }
  699.  
  700.  
  701.         else if (*(s + 1) == 'c')
  702.         {
  703.             /*
  704.              *   \c        interrupt text processing
  705.              */
  706.             s  += 2;
  707.         }
  708.  
  709.  
  710.         else if (*(s + 1) == 'd')
  711.         {
  712.             /*
  713.              *   \d        down (half line)
  714.              */
  715.             s  += 2;
  716.         }
  717.  
  718.  
  719.         else if (*(s + 1) == 'h')
  720.         {
  721.             /*
  722.              *   \h'N'    horiz motion
  723.              */
  724.             s    += 2;
  725.             delim = *s++;
  726.             val   = atoi (s);
  727.             for (i = 0; i < val; i++)
  728.                 *t++ = ' ';
  729.             while (*s != delim)
  730.             {
  731.                 if (*s == 0)
  732.                     break;
  733.                 s++;
  734.             }
  735.             if (*s)
  736.                 s++;
  737.             
  738.         }
  739.  
  740.  
  741.         else if (*(s + 1) == 'k')
  742.         {
  743.             /*
  744.              *   \kx    mark horiz place
  745.              */
  746.             s  += 2;
  747.         }
  748.  
  749.  
  750.         else if (*(s + 1) == 'l')
  751.         {
  752.             /*
  753.              *   \l'Nc'    horiz line drawing function
  754.              */
  755.             s  += 2;
  756.         }
  757.  
  758.  
  759.         else if (*(s + 1) == 'L')
  760.         {
  761.             /*
  762.              *   \L'Nc'    vertical line drawing function
  763.              */
  764.             s  += 2;
  765.         }
  766.  
  767.  
  768.         else if (*(s + 1) == 'o')
  769.         {
  770.             /*
  771.              *   \o'abc...'        overstrike
  772.              */
  773.             s  += 2;
  774.             delim = *s++;
  775.             while (*s != EOS && *s != delim)
  776.             {
  777.                 *t++ = *s++;
  778.                 *t++ = 0x08;
  779.             }
  780.             s++;
  781.         }
  782.  
  783.  
  784.         else if (*(s + 1) == 'p')
  785.         {
  786.             /*
  787.              *   \p        break and spread input line
  788.              */
  789.             s  += 2;
  790.         }
  791.  
  792.  
  793.         else if (*(s + 1) == 'r')
  794.         {
  795.             /*
  796.              *   \r        reverse line
  797.              */
  798.             s  += 2;
  799.         }
  800.  
  801.  
  802.         else if (*(s + 1) == 's')
  803.         {
  804.             int    psize;
  805.             int    bigger;
  806.             int    smaller;
  807.  
  808.             /*
  809.              *   \sN,\s+-N    point size change
  810.              */
  811.             s      += 2;
  812.             bigger  = 0;
  813.             smaller = 0;
  814.             if (*s == '-')
  815.             {
  816.                 s++;
  817.                 smaller = 1;
  818.             }
  819.             else if (*s == '+')
  820.             {
  821.                 s++;
  822.                 bigger = 1;
  823.             }
  824.  
  825.             for (psize = 0; *s >= '0' && *s <= '9'; s++)
  826.                 psize = (psize * 10) + (*s - '0');
  827.  
  828.             if (bigger || (psize >= 10) || (psize == 0))
  829.             {
  830.                 if (ansi_escapes)
  831.                 {
  832.                     strcpy (t, e_small);
  833.                     t += strlen (e_small);
  834.                 }
  835.             }
  836.             else if (smaller || (psize < 10))
  837.             {
  838.                 if (ansi_escapes)
  839.                 {
  840.                     strcpy (t, s_small);
  841.                     t += strlen (s_small);
  842.                 }
  843.             }
  844.         }
  845.  
  846.  
  847.         else if (*(s + 1) == 't')
  848.         {
  849.             /*
  850.              *   \t        horizontal tab
  851.              */
  852.             s  += 2;
  853.             *t++ = 0x09;
  854.         }
  855.  
  856.  
  857.         else if (*(s + 1) == 'u')
  858.         {
  859.             /*
  860.              *   \u        up (half line)
  861.              */
  862.             s  += 2;
  863.         }
  864.  
  865.  
  866.         else if (*(s + 1) == 'v')
  867.         {
  868.             /*
  869.              *   \v'N'    vert tab
  870.              */
  871.             s    += 2;
  872.             delim = *s++;
  873.             val   = atoi (s);
  874.             for (i = 0; i < val; i++)
  875.                 *t++ = 0x0A;
  876.             while (*s != delim)
  877.             {
  878.                 if (*s == 0)
  879.                     break;
  880.                 s++;
  881.             }
  882.             if (*s)
  883.                 s++;
  884.         }
  885.  
  886.  
  887.         else if (*(s + 1) == 'w')
  888.         {
  889.             /*
  890.              *   \w'str'    interpolate width of string
  891.              */
  892.             s  += 2;
  893.         }
  894.  
  895.  
  896.         else if (*(s + 1) == 'x')
  897.         {
  898.             /*
  899.              *   \x'N'
  900.              */
  901.             s  += 2;
  902.         }
  903.  
  904.  
  905.         else if (*(s + 1) == 'z')
  906.         {
  907.             /*
  908.              *   \zc    print c w/o spacing
  909.              */
  910.             s  += 2;
  911.             *t++ = *s++;
  912.             *t++ = 0x08;
  913.         }
  914.  
  915.  
  916.         else if (*(s + 1) == '{')
  917.         {
  918.             /*
  919.              *   \{        start if block
  920.              */
  921.             s  += 2;
  922.             *t++ = '\\';
  923.             *t++ = '{';
  924.         }
  925.  
  926.  
  927.         else if (*(s + 1) == '}')
  928.         {
  929.             /*
  930.              *   \}        end if block
  931.              */
  932.             s  += 2;
  933.             *t++ = '\\';
  934.             *t++ = '}';
  935.         }
  936.  
  937.  
  938.         else if (*(s + 1) == '\n' || *(s + 1) == '\r')
  939.         {
  940.             /*
  941.              *   \(newline)    ignore newline
  942.              */
  943.             s  += 2;
  944.         }
  945.  
  946.  
  947.         else
  948.         {
  949.             /*
  950.              *   \X        any other character not above
  951.              */
  952.             s   += 1;
  953.             *t++ = *s++;
  954.         }
  955.  
  956.     }
  957.  
  958.     /*
  959.      *   end the string and return it in original buf
  960.      */
  961.     *t = EOS;
  962.     strcpy (p, q);
  963. }
  964.  
  965.  
  966.  
  967.  
  968. /*------------------------------*/
  969. /*    specialchar        */
  970. /*------------------------------*/
  971. int specialchar (s, c)
  972. REGISTER char  *s;
  973. REGISTER char  *c;
  974. {
  975.  
  976. /*
  977.  *    handles \(xx escape sequences for special characters (atari-specific)
  978.  */
  979.  
  980.     REGISTER char    c1;
  981.     REGISTER char    c2;
  982.  
  983.     c1 = *s;
  984.     c2 = *(s+1);
  985.  
  986.     /*
  987.      *   special symbols (alt char set and std font)
  988.      */
  989.     if (ansi_escapes)
  990.     {
  991.         return (dev_char (c1, c2, c));
  992.     }
  993.     else
  994.     {
  995.  
  996.     /*
  997.      *   not ansi, just use whatever is in the standard set...
  998.      *
  999.      *   special chars
  1000.      */
  1001.     if (c1 == 'e' && c2 == 'm') {*c = 0x2D; return (2);}    /* dash */
  1002.     if (c1 == 'h' && c2 == 'y') {*c = 0x2D; return (2);}    /* hyphen */
  1003.     if (c1 == 'b' && c2 == 'u') {*c = 0xF9; return (2);}    /* bullet */
  1004.     if (c1 == 's' && c2 == 'q') {*c = 0xF9; return (2);}    /* square */
  1005.     if (c1 == 'r' && c2 == 'u') {*c = 0x5F; return (2);}    /* rule */
  1006.     if (c1 == '1' && c2 == '2') {*c = 0xAB; return (2);}    /* 1/2 */
  1007.     if (c1 == '1' && c2 == '4') {*c = 0xAC; return (2);}    /* 1/4 */
  1008.     if (c1 == 'd' && c2 == 'e') {*c = 0xF8; return (2);}    /* degree */
  1009.     if (c1 == 'd' && c2 == 'g') {*c = 0xBB; return (2);}    /* dagger */
  1010.     if (c1 == 'f' && c2 == 'm') {*c = 0xBA; return (2);}    /* dagger */
  1011.     if (c1 == 'c' && c2 == 't') {*c = 0x9B; return (2);}    /* cent */
  1012.     if (c1 == 'c' && c2 == 'o') {*c = 0xBD; return (2);}    /* copyrite */
  1013.     if (c1 == 'r' && c2 == 'g') {*c = 0xBE; return (2);}    /* registered */
  1014.     if (c1 == 't' && c2 == 'm') {*c = 0xBF; return (2);}    /* trademark */
  1015.  
  1016.     if (c1 == 'p' && c2 == '2') {*c = 0xFD; return (2);}    /* ^2 */
  1017.     if (c1 == 'p' && c2 == '3') {*c = 0xFE; return (2);}    /* ^3 */
  1018.     if (c1 == 'p' && c2 == 'n') {*c = 0xFC; return (2);}    /* ^n */
  1019.     if (c1 == 'a' && c2 == 'a') {*c = 0xBA; return (2);}    /* acute */
  1020.     if (c1 == 'g' && c2 == 'a') {*c = 0x60; return (2);}    /* grave */
  1021.     if (c1 == 'd' && c2 == 't') {*c = 0xFA; return (2);}    /* dot */
  1022.     if (c1 == 'p' && c2 == 'p') {*c = 0xBC; return (2);}    /* paragraph */
  1023.     if (c1 == '^' && c2 == 'g') {*c = 0x07; return (2);}    /* ring bell */
  1024.     if (c1 == 'u' && c2 == 'a') {*c = 0x01; return (2);}    /* up arrow */
  1025.     if (c1 == 'd' && c2 == 'a') {*c = 0x02; return (2);}    /* dn arrow */
  1026.     if (c1 == '-' && c2 == '>') {*c = 0x03; return (2);}    /* rt arrow */
  1027.     if (c1 == '<' && c2 == '-') {*c = 0x04; return (2);}    /* lf arrow */
  1028.     if (c1 == 'd' && c2 == 'i') {*c = 0xF6; return (2);}    /* divide */
  1029.     if (c1 == 's' && c2 == 'r') {*c = 0xFB; return (2);}    /* sq root */
  1030.     if (c1 == '=' && c2 == '=') {*c = 0xF0; return (2);}    /* == */
  1031.     if (c1 == '>' && c2 == '=') {*c = 0xF2; return (2);}    /* >= */
  1032.     if (c1 == '<' && c2 == '=') {*c = 0xF3; return (2);}    /* <= */
  1033.     if (c1 == '+' && c2 == '-') {*c = 0xF1; return (2);}    /* +- */
  1034.     if (c1 == '~' && c2 == '=') {*c = 0xF7; return (2);}    /* ~= */
  1035.     if (c1 == 'a' && c2 == 'p') {*c = 0x7E; return (2);}    /* approx */
  1036.     if (c1 == 'n' && c2 == 'o') {*c = 0xAA; return (2);}    /* not */
  1037.     if (c1 == 'm' && c2 == 'o') {*c = 0xEE; return (2);}    /* member */
  1038.     if (c1 == 'c' && c2 == 'a') {*c = 0xEF; return (2);}    /* intersect */
  1039.     if (c1 == 'c' && c2 == 'u') {*c = 0x55; return (2);}    /* union */
  1040.     if (c1 == 'i' && c2 == '1') {*c = 0xF4; return (2);}    /* integral1 */
  1041.     if (c1 == 'i' && c2 == '2') {*c = 0xF5; return (2);}    /* integral2 */
  1042.  
  1043.     if (c1 == 'b' && c2 == 'r') {*c = 0x7C; return (2);}    /* box v rule */
  1044.     if (c1 == 'b' && c2 == 'v') {*c = 0x7C; return (2);}    /* bold vert */
  1045.     if (c1 == 'p' && c2 == 'l') {*c = 0x2B; return (2);}    /* math plus */
  1046.     if (c1 == 'm' && c2 == 'i') {*c = 0x2D; return (2);}    /* math minus */
  1047.     if (c1 == 'e' && c2 == 'q') {*c = 0x3D; return (2);}    /* math equal */
  1048.     if (c1 == '*' && c2 == '*') {*c = 0x2A; return (2);}    /* math star */
  1049.     if (c1 == 's' && c2 == 'l') {*c = 0x2F; return (2);}    /* slash */
  1050.     if (c1 == 'u' && c2 == 'l') {*c = 0x5F; return (2);}    /* underrule */
  1051.     if (c1 == 's' && c2 == 'c') {*c = 0xDD; return (2);}    /* section */
  1052.  
  1053.  
  1054.     /*
  1055.      *   greek
  1056.      */
  1057.     if (c1 == '*' && c2 == 'a') {*c = 0xE0; return (2);}    /* alpha */
  1058.     if (c1 == '*' && c2 == 'b') {*c = 0xE1; return (2);}    /* beta */
  1059.     if (c1 == '*' && c2 == 'g') {*c = 0xE2; return (2);}    /* gamma */
  1060.     if (c1 == '*' && c2 == 'd') {*c = 0x7F; return (2);}    /* delta */
  1061.     if (c1 == '*' && c2 == 's') {*c = 0xE4; return (2);}    /* sigma */
  1062.     if (c1 == '*' && c2 == 'p') {*c = 0xE3; return (2);}    /* pi */
  1063.     if (c1 == '*' && c2 == 'm') {*c = 0xE6; return (2);}    /* mu */
  1064.  
  1065.     }
  1066.  
  1067.  
  1068.     /*
  1069.      *   if we get here, we do no support the escape. send back a space.
  1070.      *   caller will push the 2 char escape sequence to output.
  1071.      */
  1072.     *c = ' ';
  1073.  
  1074.     return (0);    
  1075. }
  1076.  
  1077.  
  1078.  
  1079.  
  1080. /*------------------------------*/
  1081. /*    fontchange        */
  1082. /*------------------------------*/
  1083. void fontchange (fnt, s)
  1084. char    fnt;
  1085. char   *s;
  1086. {
  1087.  
  1088. /*
  1089.  *    handles \fx font change escapes for R,B,I,S,P (atari-specific)
  1090.  *    resets current and last font in dc struct (last used for .ft
  1091.  *    with no args)
  1092.  */
  1093.  
  1094.     int    tmp;
  1095.  
  1096.     *s = '\0';
  1097.     switch (fnt)
  1098.     {
  1099.     case 'R':                /* Times Roman */
  1100.         if (dc.dofnt == YES)
  1101.         {
  1102.             if (ansi_escapes)
  1103.                 strcpy (s, e_all);
  1104.             else
  1105.                 strcpy (s, e_standout);
  1106.         }
  1107.         dc.lastfnt = dc.thisfnt;
  1108.         dc.thisfnt = 1;
  1109.         break;
  1110.     case 'I':                /* Times italic */
  1111.         if (dc.dofnt == YES)
  1112.         {
  1113.             if (ansi_escapes)
  1114.                 strcpy (s, s_italic);
  1115.             else
  1116.                 strcpy (s, s_standout);
  1117.         }
  1118.         dc.lastfnt = dc.thisfnt;
  1119.         dc.thisfnt = 2;
  1120.         break;
  1121.     case 'B':                /* Times bold */
  1122.         if (dc.dofnt == YES)
  1123.         {
  1124.             if (ansi_escapes)
  1125.                 strcpy (s, s_bold);
  1126.             else
  1127.                 strcpy (s, s_standout);
  1128.         }
  1129.         dc.lastfnt = dc.thisfnt;
  1130.         dc.thisfnt = 3;
  1131.         break;
  1132.     case 'S':                /* math/special */
  1133.         if (ansi_escapes)
  1134.         {
  1135.             if (dc.dofnt == YES)
  1136.             {
  1137.                 strcpy (s, s_special);
  1138.             }
  1139.             dc.lastfnt = dc.thisfnt;
  1140.             dc.thisfnt = 4;
  1141.         }
  1142.         else
  1143.         {
  1144.             *s = '\0';
  1145.             dc.lastfnt = dc.thisfnt;
  1146.             dc.thisfnt = 4;
  1147.         }
  1148.         break;
  1149.     case 'P':                /* previous (exchange) */
  1150.         if (dc.dofnt == YES)
  1151.         {
  1152.             if (ansi_escapes)
  1153.             {
  1154.                 if (dc.lastfnt == 1)
  1155.                     strcpy (s, e_all);    /* to R */
  1156.                 else if (dc.lastfnt == 2)
  1157.                     strcpy (s, s_italic);    /* to I */
  1158.                 else if (dc.lastfnt == 3)
  1159.                     strcpy (s, s_bold);    /* to B */
  1160.                 else if (dc.lastfnt == 4)
  1161.                     strcpy (s, s_special);    /* to S */
  1162.                 else
  1163.                     *s = '\0';        /* nothing */
  1164.             }
  1165.             else
  1166.             {
  1167.                 if (dc.lastfnt == 1)
  1168.                     strcpy (s, e_standout);    /* to R */
  1169.                 else if (dc.lastfnt == 2)
  1170.                     strcpy (s, s_standout);    /* to I */
  1171.                 else if (dc.lastfnt == 3)
  1172.                     strcpy (s, s_standout);    /* to B */
  1173.                 else
  1174.                     *s = '\0';        /* nothing */
  1175.             }
  1176.         }
  1177.  
  1178.         tmp        = dc.thisfnt;        /* swap this/last */
  1179.         dc.thisfnt = dc.lastfnt;
  1180.         dc.lastfnt = tmp;
  1181.         break;
  1182.     default:
  1183.         *s = '\0';
  1184.         break;
  1185.     }
  1186.  
  1187.     set_ireg (".f", dc.thisfnt, 0);
  1188. }
  1189.  
  1190.  
  1191.  
  1192.  
  1193.  
  1194. /*------------------------------*/
  1195. /*    findreg            */
  1196. /*------------------------------*/
  1197. int findreg (name)
  1198. REGISTER char  *name;
  1199. {
  1200.  
  1201. /*
  1202.  *    find register named 'name' in pool. return index into array or -1
  1203.  *    if not found.
  1204.  */
  1205.  
  1206.     REGISTER int    i;
  1207.     REGISTER char  *prname;
  1208.  
  1209.     for (i = 0; i < MAXREGS; i++)
  1210.     {
  1211.         prname = rg[i].rname;
  1212. /*DBG
  1213. fprintf(stderr,"findreg: stored: |%c%c| (%02x%02x) test: |%c%c| (%02x%02x)\n",
  1214. (int)(*prname),(int)(*(prname+1)),(int)(*prname),(int)(*(prname+1)),
  1215. (int)(*name),(int)(*(name+1)),(int)(*name),(int)(*(name+1)));
  1216. */
  1217.         if (*prname == *name && *(prname + 1) == *(name + 1))
  1218.             break;
  1219.     }
  1220.  
  1221.     return ((i < MAXREGS) ? i : -1);
  1222. }
  1223.  
  1224.  
  1225.  
  1226.  
  1227.